package com.starnet.yarnmonitor.security.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.starnet.yarnmonitor.security.entity.SysRole;
import com.starnet.yarnmonitor.security.entity.SysUser;
import com.starnet.yarnmonitor.security.entity.SysUserRoleRelation;
import com.starnet.yarnmonitor.security.mapper.SysRoleMapper;
import com.starnet.yarnmonitor.security.mapper.SysUserMapper;
import com.starnet.yarnmonitor.security.mapper.SysUserRoleRelationMapper;
import com.starnet.yarnmonitor.security.service.SysUserService;
import com.starnet.yarnmonitor.security.utils.RedisCache;
import com.starnet.yarnmonitor.security.vo.param.AddUserParam;
import com.starnet.yarnmonitor.security.vo.param.ModifyPasswordParam;
import com.starnet.yarnmonitor.yarn.handler.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.LocalDateTime;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author 陈佳豪
 * @since 2022-05-16
 */
@Slf4j
@Service
public class SysUserServiceImpl implements SysUserService {
    @Autowired
    SysUserMapper sysUserMapper;
    @Autowired
    SysUserRoleRelationMapper sysUserRoleRelationMapper;
    @Autowired
    SysRoleMapper sysRoleMapper;
    @Autowired
    PasswordEncoder passwordEncoder;
    @Autowired
    RedisCache redisCache;


    @Override
    public SysUser selectByAccount(String userName) {
        SysUser sysUser = sysUserMapper.selectByAccount(userName);
        return sysUser;
    }


    @Transactional
    @Override
    public void addUser(AddUserParam addUserParam) {
        //如果没指定用户角色，就赋予普通用户
        if (addUserParam.getRoleName()==null){
            addUserParam.setRoleName("普通用户");
        }
        String account = addUserParam.getAccount();
        //检查是否已经注册过
        SysUser sysUserInDB = sysUserMapper.selectByAccount(account);
        if (sysUserInDB != null) {
            throw new ApiException("该账号已被注册");
        }
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(addUserParam, sysUser);
        sysUser.init();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //获取当前创建人信息
        User creator = (User) authentication.getPrincipal();
        //这里的creatorUsername对应数据库中的account
        String creatorUsername = creator.getUsername();
        Integer creatorId = sysUserMapper.selectByAccount(creatorUsername).getId();
        //设置新用户的创建人为当前
        sysUser.setCreateUser(creatorId);
        sysUser.setUpdateUser(creatorId);
        sysUserMapper.insert(sysUser);

        //赋予用户角色
        LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysRole::getRoleName, addUserParam.getRoleName());
        SysRole sysRole = sysRoleMapper.selectOne(queryWrapper);
        if (sysRole == null) {
            throw new ApiException("创建失败,不存在该角色");
        }

        SysUserRoleRelation sysUserRoleRelation = new SysUserRoleRelation(null, sysUser.getId(), sysRole.getId());
        sysUserRoleRelationMapper.insert(sysUserRoleRelation);
        log.info("账号:"+account+"新增了一个用户:"+sysUser,"，角色为:"+addUserParam.getRoleName());

    }

    @Override
    public void modifyPassword(ModifyPasswordParam modifyPasswordParam) {
       //获取token认证上下文
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User user = (User) authentication.getPrincipal();
        //这里的username其实是account 因为security里面的username代表用户唯一标识
        String account = user.getUsername();
        SysUser sysUser = selectByAccount(account);
        boolean matches = passwordEncoder.matches(modifyPasswordParam.getOldPassword(), sysUser.getPassword());
        if (!matches){
            throw new ApiException("旧密码错误，修改失败");
        }
        String newPassword = modifyPasswordParam.getNewPassword();;
        //经BCryptEncoder加密后放入数据库
        newPassword=passwordEncoder.encode(newPassword);
        sysUser.setPassword(newPassword);
        //设置更新人 和更新时间
        sysUser.setUpdateUser(sysUser.getId());
        sysUser.setUpdateTime(Timestamp.valueOf(LocalDateTime.now()));
        sysUserMapper.updateById(sysUser);
        log.info("账号"+account+"修改了密码");
        //使之前的token失效，删除redis里的旧密码token，要求用户重新登录
        redisCache.deleteObject("login:"+account);

    }


}
